#include "kbox_rbtree.h"

// rbtree api
rbtree *tree = NULL;
int KBoxRbtreeCreate()
{
	if (tree)
		return -1;

	tree = (rbtree *)KBoxMalloc(sizeof(rbtree));
	memset(tree, 0, sizeof(rbtree));

	tree->nil = (rbtree_node *)KBoxMalloc(sizeof(rbtree_node));
	tree->nil->key = KBoxMalloc(1);
	*(tree->nil->key) = '\0';

	tree->nil->color = BLACK;
	tree->root = tree->nil;

	return 0;
}

void KBoxRbtreeDestory()
{
	if (!tree)
		return;

	if (tree->nil->key)
		KBoxFree(tree->nil->key);

	rbtree_node *node = tree->root;
	if (node == tree->nil)
	{
		KBoxFree(tree->nil);
		KBoxFree(tree);
		return;
	}
	while ((node = rbtree_mini(tree, tree->root)) != tree->nil)
	{

		if (node == tree->nil)
		{
			break;
		}

		node = rbtree_delete(tree, node);

		if (node)
		{
			KBoxFree(node->key);
			KBoxFree(node->value);
			KBoxFree(node);
		}
	}

	if (node)
	{
		KBoxFree(node->key);
		KBoxFree(node->value);
		KBoxFree(node);
	}

	if (tree)
		KBoxFree(tree);
}

int KBoxRbtreeSet(char *key, char *value)
{

	rbtree_node *node = (rbtree_node *)malloc(sizeof(rbtree_node));
	if (!node)
		return -1;

	node->key = KBoxMalloc(strlen(key) + 1);
	if (node->key == NULL)
	{
		KBoxFree(node);
		return -1;
	}

	memset(node->key, 0, strlen(key) + 1);
	strcpy(node->key, key);

	node->value = KBoxMalloc(strlen(value) + 1);
	if (node->value == NULL)
	{
		KBoxFree(node->key);
		KBoxFree(node);
		return -1;
	}
	memset(node->value, 0, strlen(value) + 1);
	strcpy((char *)node->value, value);

	rbtree_insert(tree, node);
	tree->count++;

	return 0;
}

char *KBoxRbtreeGet(char *key)
{

	rbtree_node *node = rbtree_search(tree, key);
	if (node == tree->nil)
	{
		return NULL;
	}

	return node->value;
}

int KBoxRbtreeDelete(char *key)
{

	rbtree_node *node = rbtree_search(tree, key);
	if (node == tree->nil)
	{
		return -1;
	}

	rbtree_node *cur = rbtree_delete(tree, node);

	if (cur)
	{
		KBoxFree(cur->key);
		KBoxFree(cur->value);
		KBoxFree(cur);
	}
	tree->count--;

	return 0;
}

int KBoxRbtreeModify(char *key, char *value)
{

	rbtree_node *node = rbtree_search(tree, key);
	if (node == tree->nil)
	{
		return -1;
	}

	char *tmp = node->value;
	KBoxFree(tmp);

	node->value = KBoxMalloc(strlen(value) + 1);
	if (node->value == NULL)
	{
		return -1;
	}
	strcpy(node->value, value);

	return 0;
}

int KBoxRbtreeCount()
{
	if (!tree)
		return -1;
	return tree->count;
}
